<template>
  <div
    ref="virtallistContainer"
    class="virtallist-container"
    @scroll="handlScroll"
  >
    <div ref="virtallistScrollBar" class="virtallist-scroll-bar"></div>
    <div
      class="virtallist-scroll-list"
      :style="{ transform: `translate3d(0, ${offset}px, 0)` }"
    >
      <div
        v-for="item in visibleData"
        ref="virtallistScrollList"
        :key="item.key"
        :vid="item.key"
      >
        <!-- 通过插槽传出去 -->
        <slot :item="item"></slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    options: {
      type: Array,
      default: () => []
    },
    size: {
      type: Number,
      default: 0
    },
    remain: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      start: 0,
      end: 0,
      offset: 0
    };
  },
  computed: {
    //前面预留几个
    prevCount() {
      return Math.min(this.start, this.remain);
    },
    //后面预留几个
    nextCount() {
      return Math.min(this.remain, this.options.length - this.end);
    },
    //可见数据有哪些
    visibleData() {
      let start = this.start - this.prevCount;
      let end = this.end + this.nextCount;
      return this.options.slice(start, end);
    }
  },
  watch: {
    options(newVal, oldVal) {
      if (newVal !== oldVal) {
        this.init();
      }
    }
  },
  mounted() {
    this.end = this.remain;
    this.init();
  },
  methods: {
    init() {
      //当前的一项高度*显示的项目高度
      this.$refs.virtallistContainer.style.height =
        this.size * this.remain + "px";

      //当前总长度*当前的项目高度
      this.$refs.virtallistScrollBar.style.height =
        this.options.length * this.size + "px";
    },
    handlScroll() {
      //列表开始的位置应该额等于滚动的位置/列表的高度
      this.start = Math.floor(
        this.$refs.virtallistContainer.scrollTop / this.size
      );

      //要渲染列表结束的位置等于列表开始的位置加上每一页数据展示的高度
      this.end = this.start + this.remain;

      //如果前面有预留渲染，应该把这个位置向上移动
      this.offset = this.start * this.size - this.prevCount * this.size;
    }
  }
};
</script>

<style lang="less" scoped>
.virtallist-container {
  overflow-y: scroll;
  position: relative;

  .virtallist-scroll-list {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}
</style>
